﻿import QtQuick.Controls 1.4 as Control1
import QtQuick.Controls.Styles 1.4
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12

Control1.TableView {
    id: controlRoot

    //数据模型
    //每行数据的格式为：{"columnRole1":value1,"columnRole2":value2,"checked":false}
    //其中columnRole1为该行所在列的角色名，value1为该行所在列的值，checked为该行是否勾选（如果showSelectColumn为false，则无需指定）
    property alias listModel: listModel

    //视图样式
    property color viewBgColor: "white"
    property color viewBorderColor: "#9F9F9F"
    property int   viewBorderWidth: 1

    //表头样式
    property int   headerHeight: 30
    property int   headerTextSize: 18
    property var   headerTextColor: "black"
    property color headerBorderColor: viewBorderColor
    property color headerRightGridColor: viewBorderColor
    property int   headerRightGridWidth: viewBorderWidth
    property color headerBottomGridColor: viewBorderColor
    property int   headerBottomGridWidth: viewBorderWidth
    property Gradient headerBgGradient: Gradient {
        GradientStop {
            position: 0.0
            color: "#F6F6F6"
        }
        GradientStop {
            position: 0.5
            color: "#E0E0E0"
        }
        GradientStop {
            position: 1
            color: "#DFDFE0"
        }
    }
    property var   headerBgFillColor

    //行样式
    property int   rowHeight: 28
    property color rowBgNormalColor: "white"
    property color rowBgAlternateColor: "#F0FFF0"
    property color rowBgSelectedColor: "#0078D7"

    //单元格样式
    property int   itemTextSize: 17
    property color itemTextNormalColor: "black"
    property color itemTextSelectedColor: "white"
    property color itemGridColor: viewBorderColor
    property int   itemGridWidth: viewBorderWidth
    property bool  itemRightGridVisible: true
    property bool  itemBottomGridVisible: true

    //复选框样式
    property color checkBoxBgCheckedColor: "#409eff"
    property color checkBoxBgUncheckedColor: "white"
    property color checkBoxBorderCheckedColor: checkBoxBgCheckedColor
    property color checkBoxBorderUncheckedColor: "#c0c0c0"
    property color checkBoxTickColor:"white"
    property real  checkBoxTickLineWidth: 2

    //滚动设置
    property int  scrollRowCount: 5      //单次滚动的行数
    property bool scrollWholePage: true  //整屏滚动，设置此值时将忽略scrollRowCount
    property int  animationTime: 300     //滚动动画持续时间

    //其他设置
    property bool useNativeRender: false    //单元格字体使用本地渲染
    property bool showSelectColumn: true    //是否显示勾选列（固定显示在第一列）

    //信号
    signal itemClick(var mouse, var row, var column)    //点击某个单元格时触发(点击勾选列，则不会触发)

    clip: true
    width: 800
    height: 600
    model: listModel
    frameVisible: false
    backgroundVisible: true
    itemDelegate: item
    rowDelegate: row
    headerDelegate: head

    style: TableViewStyle { //视图背景
        backgroundColor: viewBgColor
    }

    Component.onCompleted: { //创建选择列
        if (showSelectColumn) {
            var columnObj = selectColumn.createObject(controlRoot, {})
            controlRoot.insertColumn(0, selectColumn)
        }
    }

    Rectangle { //视图边框
        color: "transparent"
        anchors.fill: parent
        border.width: viewBorderWidth
        border.color: viewBorderColor
    }

    MouseArea { //处理列表滚动
        anchors.fill: parent
        acceptedButtons: Qt.MidButton
        onWheel: {
            var rowTotalHeight = listModel.count * rowHeight
            if (rowTotalHeight <= controlRoot.height - headerHeight) {
                //行数不足时不滚动
                return
            }

            if (wheel.angleDelta.y > 0) {
                //向上滚动
                var pos
                if (scrollWholePage) {
                    var count = Math.floor(
                                (controlRoot.height - headerHeight) / rowHeight)
                    pos = controlRoot.flickableItem.contentY - rowHeight * count
                } else {
                    pos = controlRoot.flickableItem.contentY - rowHeight * scrollRowCount
                }
                if (pos >= -headerHeight) {
                    //向上滚动的最顶端为表头之下
                    animation.to = pos
                    animation.restart()
                } else {
                    animation.to = -headerHeight
                    animation.restart()
                }
            } else {
                //向下滚动
                var pos2
                if (scrollWholePage) {
                    var count2 = Math.floor(
                                (controlRoot.height - headerHeight) / rowHeight)
                    pos2 = controlRoot.flickableItem.contentY + rowHeight * count2
                } else {
                    pos2 = controlRoot.flickableItem.contentY + rowHeight * scrollRowCount
                }

                if (pos2 <= controlRoot.flickableItem.contentHeight
                        - controlRoot.height - headerHeight) {
                    animation.to = pos2
                    animation.restart()
                } else {
                    animation.to = controlRoot.flickableItem.contentHeight
                            - controlRoot.height - headerHeight
                    animation.restart()
                }
            }
        }

        PropertyAnimation {
            id: animation
            target: controlRoot.flickableItem
            property: "contentY"
            duration: animationTime
        }
    }

    ListModel { //数据模型
        id: listModel
    }

    Component { //表头组件
        id: head
        Rectangle {
            id: headCompBack

            property Gradient headerFillGradient: Gradient {//此属性在设置了headerBgFillColor时用于填充纯色背景
                GradientStop {
                    position: 1
                    color: headerBgFillColor === undefined ? "white" : headerBgFillColor
                }
            }

            gradient: {
                if (headerBgFillColor !== undefined) {
                    return headerFillGradient
                } else {
                    return headerBgGradient
                }
            }
            height: headerHeight

            Text {//标题文字
                id: headerText
                text: styleData.value
                color: headerTextColor
                textFormat: Text.RichText
                font.pixelSize: headerTextSize
                renderType: useNativeRender ? Text.NativeRendering : Text.QtRendering
                anchors.fill: parent
                horizontalAlignment: Text.AlignHCenter
                verticalAlignment: Text.AlignVCenter
                visible:styleData.column===0?(showSelectColumn?false:true):true
            }



            Rectangle {
                //表头右侧线宽度
                height: parent.height
                color: headerRightGridColor
                width: headerRightGridWidth
                anchors.right: parent.right
                visible: {
                    if (styleData.column < 0) {
                        return false
                    } else if (styleData.column === (controlRoot.columnCount - 1)) {
                        return false
                    } else {
                        return true
                    }
                }
            }

            Rectangle {
                //表头底部网格线
                color: headerBottomGridColor
                height: headerBottomGridWidth
                width: parent.width
                anchors.bottom: parent.bottom
                visible: true
            }
        }
    }

    Component { //行组件
        id: row
        Rectangle {
            color: {
                if (controlRoot.selectionMode === 0) {
                    return styleData.alternate ? rowBgAlternateColor : rowBgNormalColor
                } else {
                    return styleData.selected ? rowBgSelectedColor : (styleData.alternate ? rowBgAlternateColor : rowBgNormalColor)
                }
            }
            height: rowHeight

            Rectangle {
                color: itemGridColor
                height: itemGridWidth
                width: parent.width
                anchors.bottom: parent.bottom
                visible: {
                    if (itemBottomGridVisible
                            && (styleData.row < listModel.count)) {
                        return true
                    } else {
                        return false
                    }
                }
            }

            MouseArea {
                //截取鼠标事件，否则点击空行空列时会导致焦点乱飘
                anchors.fill: parent
                enabled: true
            }
        }
    }

    Component { //单元格组件
        id: item
        Text {
            id: itemText
            elide: styleData.elideMode
            text: {
                if (styleData.role === "index") {
                    return styleData.value
                } else {
                    if (styleData.value === undefined) {
                        return ""
                    } else {
                        return styleData.value
                    }
                }
            }
            color: styleData.selected ? itemTextSelectedColor : itemTextNormalColor
            horizontalAlignment: styleData.textAlignment
            verticalAlignment: Text.AlignVCenter
            font.pixelSize: itemTextSize
            renderType: useNativeRender ? Text.NativeRendering : Text.QtRendering
            anchors.fill: parent

            Rectangle {
                //单元格右侧网格线
                color: itemGridColor
                height: parent.height
                width: itemGridWidth
                anchors.right: parent.right
                visible: {
                    if (!itemRightGridVisible) {
                        return false
                    } else if (styleData.column < 0) {
                        return false
                    } else if (styleData.column === (controlRoot.columnCount - 1)) {
                        return false
                    } else {
                        return true
                    }
                }
            }

            MouseArea {
                //item必须截取鼠标事件，否则点击时会导致焦点乱飘
                anchors.fill: parent
                enabled: true
                acceptedButtons: Qt.AllButtons
                onClicked: {
                    itemText.forceActiveFocus()
                    if (controlRoot.selectionMode !== 0) {
                        controlRoot.selection.clear()
                        controlRoot.selection.select(styleData.row)
                    }

                    if (styleData.row === controlRoot.currentRow) {
                        itemClick(mouse, styleData.row, styleData.column)
                    }
                }
            }
        }
    }

    Component { //复选框列组件
        id: selectColumn
        Control1.TableViewColumn {            
            title: ""
            role: "checked"
            width: 50
            resizable: false
            movable: false
            horizontalAlignment: Text.AlignHCenter
            delegate: Item {
                id:checkBoxItem

                CheckBox {  //复选框
                    id: itemCheckBox
                    height: rowHeight*0.7
                    anchors.centerIn: parent
                    checked: styleData.value

                    indicator: Rectangle {
                        id:indicatorBack1
                        width: itemCheckBox.height
                        height:  itemCheckBox.height
                        x: itemCheckBox.leftPadding
                        y: itemCheckBox.height / 2 - height / 2
                        radius: 3
                        color:itemCheckBox.checked?checkBoxBgCheckedColor:checkBoxBgUncheckedColor
                        border.color: itemCheckBox.checked?checkBoxBorderCheckedColor:checkBoxBorderUncheckedColor

                        Canvas {
                            id: tickCanvas1
                            width: indicatorBack1.width*0.7
                            height: indicatorBack1.width*0.65
                            anchors.centerIn: parent
                            contextType: "2d"

                            Connections {
                                target: itemCheckBox
                                onCheckedChanged: tickCanvas1.requestPaint()
                            }

                            onPaint: {
                                var context = getContext("2d");
                                context.clearRect(0,0,tickCanvas1.width,tickCanvas1.height);

                                if(itemCheckBox.checked)
                                {
                                    context.lineJoin="round"
                                    context.lineCap="round"
                                    context.lineWidth = checkBoxTickLineWidth
                                    context.strokeStyle = checkBoxTickColor;
                                    context.beginPath();
                                    context.moveTo(checkBoxTickLineWidth, tickCanvas1.height/2);
                                    context.lineTo(tickCanvas1.width/2-checkBoxTickLineWidth/2, tickCanvas1.height-checkBoxTickLineWidth);
                                    context.lineTo(tickCanvas1.width-checkBoxTickLineWidth, checkBoxTickLineWidth);
                                    context.stroke();
                                }
                            }
                        }
                    }

                    onReleased: {
                        headerCheckBox.checked = false
                        listModel.setProperty(styleData.row,"checked",itemCheckBox.checked)
                    }
                }

                Rectangle { //单元格右侧网格线
                    color: itemGridColor
                    height: parent.height
                    width: itemGridWidth
                    anchors.right: parent.right
                    visible: true
                }
            }
        }
    }

    CheckBox {  //头部全选复选框
        id:headerCheckBox
        x:50/2-headerCheckBox.width/2-controlRoot.flickableItem.contentX
        y:headerHeight/2-headerCheckBox.height/2
        height: rowHeight*0.7
        enabled: visible
        visible: showSelectColumn

        indicator: Rectangle {
            id:indicatorBack2
            width: headerCheckBox.height
            height:  headerCheckBox.height
            x: headerCheckBox.leftPadding
            y: headerCheckBox.height / 2 - height / 2
            radius: 3
            color:headerCheckBox.checked?checkBoxBgCheckedColor:checkBoxBgUncheckedColor
            border.color: headerCheckBox.checked?checkBoxBorderCheckedColor:checkBoxBorderUncheckedColor

            Canvas {
                id: tickCanvas2
                width: indicatorBack2.width*0.7
                height: indicatorBack2.width*0.65
                anchors.centerIn: parent
                contextType: "2d"

                Connections {
                    target: headerCheckBox
                    onCheckedChanged: tickCanvas2.requestPaint()
                }

                onPaint: {
                    var context = getContext("2d");
                    context.clearRect(0,0,tickCanvas2.width,tickCanvas2.height);

                    if(headerCheckBox.checked)
                    {
                        context.lineJoin="round"
                        context.lineCap="round"
                        context.lineWidth = checkBoxTickLineWidth
                        context.strokeStyle = checkBoxTickColor;
                        context.beginPath();
                        context.moveTo(checkBoxTickLineWidth, tickCanvas2.height/2);
                        context.lineTo(tickCanvas2.width/2-checkBoxTickLineWidth/2, tickCanvas2.height-checkBoxTickLineWidth);
                        context.lineTo(tickCanvas2.width-checkBoxTickLineWidth, checkBoxTickLineWidth);
                        context.stroke();
                    }
                }
            }
        }

        onReleased: {
            //不应在down、clicked或doubleclicked时发出信号，因为此时checked状态不明确
            __setAllChecked(headerCheckBox.checked)
        }
    }


    //设置列可见性，可使用索引或列名(必须在组件加载完后调用)
    function setColumnVisible(column, visible) {
        if (typeof (column) == typeof (1)) {
            var columnObj1 = controlRoot.getColumn(column)
            if (columnObj1) {
                columnObj1.visible = visible
            }
        } else if (typeof (column) == typeof ("")) {
            for (var i = 0; i < controlRoot.columnCount; i++) {
                var columnObj2 = controlRoot.getColumn(i)
                if (columnObj2.title === column) {
                    columnObj2.visible = visible
                    break
                }
            }
        }
    }

    //设置列的位置，可使用索引或列名(必须在组件加载完后调用)
    function setColumnPostion(column, pos) {
        if (typeof (column) == typeof (1)) {
            var columnObj1 = controlRoot.getColumn(column)
            if (columnObj1) {
                controlRoot.moveColumn(column, pos)
            }
        } else if (typeof (column) == typeof ("")) {
            for (var i = 0; i < controlRoot.columnCount; i++) {
                var columnObj2 = controlRoot.getColumn(i)
                if (columnObj2.title === column) {
                    columnObj2.visible = visible
                    controlRoot.moveColumn(i, pos)
                    break
                }
            }
        }
    }

    //设置列的位置及可见性，可使用索引或列名(必须在组件加载完后调用)
    function setColumnVisibleAndPostion(column, visible, pos) {
        if (typeof (column) == typeof (1)) {
            var columnObj1 = controlRoot.getColumn(column)
            if (columnObj1) {
                columnObj1.visible = visible
                controlRoot.moveColumn(column, pos)
            }
        } else if (typeof (column) == typeof ("")) {
            for (var i = 0; i < controlRoot.columnCount; i++) {
                var columnObj2 = controlRoot.getColumn(i)
                if (columnObj2) {
                    if (columnObj2.title === column) {
                        columnObj2.visible = visible
                        controlRoot.moveColumn(i, pos)
                        break
                    }
                }
            }
        }
    }

    //自动计算各列最佳宽度
    function resizeAllColumn() {

        //使列宽刚好能够包容该列最宽的item
        controlRoot.resizeColumnsToContents()

        //比较当前列宽与表头最佳列宽，取较大值
        for(var i=0;i < controlRoot.columnCount; i++){
            var columnObj = controlRoot.getColumn(i)
            var columnTitle = columnObj.title
            var itemWidth = columnObj.width
            var headerBestWidth = columnTitle.length*headerTextSize

            if(headerBestWidth>itemWidth){
                columnObj.width = headerBestWidth;
            }
        }
    }

    //设置所有行的复选框状态(内部使用)
    function __setAllChecked(checked){
        for(var i = 0;i<controlRoot.listModel.count;i++){
            controlRoot.listModel.setProperty(i,"checked",checked)
        }
    }

}
